package com.ticket.sass.admin.business.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ticket.sass.admin.business.TicketOrderBusiness;
import com.ticket.sass.admin.dto.input.LaterPayRefundStatusInput;
import com.ticket.sass.admin.dto.input.order.RefundRecordInput;
import com.ticket.sass.admin.dto.input.order.TakeTicketOrderInput;
import com.ticket.sass.admin.dto.output.order.OrderDataModel;
import com.ticket.sass.admin.dto.output.order.RefundApplyRecordListOutput;
import com.ticket.sass.admin.dto.output.order.TakeTicketOrderOutPut;
import com.ticket.sass.admin.dto.output.order.TakeTicketOutPut;
import com.ticket.sass.admin.model.PageModel;
import com.ticket.sass.admin.service.impl.*;
import com.ticket.sass.admin.util.EscapeUtil;
import com.ticket.sass.admin.manager.GeneratorCodeManager;
import com.ticket.sass.admin.util.ModelUtil;
import com.ticket.sass.common.entity.tenant.*;
import com.ticket.sass.common.entity.tenant.enums.MemberCardOrderRecordFlowType;
import com.ticket.sass.common.entity.tenant.enums.MemberCardOrderRecordType;
import com.ticket.sass.common.entity.tenant.enums.OrderTicketLaterPayStatus;
import com.ticket.sass.common.exception.enums.ErrorCode;
import com.ticket.sass.common.exception.exception.BadRequestException;
import lombok.AllArgsConstructor;
import org.modelmapper.TypeToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ywb
 * @date 2022-03-25 14:28
 */
@Service
@AllArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class TicketOrderBusinessImpl implements TicketOrderBusiness {
    final ModelUtil modelUtil;
    final UserServiceImpl userService;
    final OrderServiceImpl orderService;
    final TakeTicketOrderServiceImpl service;
    final TakeTicketServiceImpl ticketService;
    final MemberCardServiceImpl memberCardService;
    final OrderTicketServiceImpl orderTicketService;
    final GeneratorCodeManager generateSerialNumber;
    final FilmScheduleServiceImpl filmScheduleService;
    final MemberCardOrderRecordServiceImpl orderRecordService;
    final OrderTicketLaterPayServiceImpl orderTicketLaterPayService;
    final LaterPayRefundRecordServiceImpl refundApplyRecordsService;
    final MemberCardOrderRecordServiceImpl memberCardOrderRecordService;

    
    @Override
    public OrderDataModel<TakeTicketOrderOutPut> list(TakeTicketOrderInput input) {
        IPage<TakeTicketOrderEntity> page = service.list(input);
        List<TakeTicketOrderOutPut> outPuts = modelUtil.listToList(
            page.getRecords(),
            new TypeToken<List<TakeTicketOrderOutPut>>() { }.getType()
        );
        
        List<Long> orderIds  = outPuts.stream().map(TakeTicketOrderOutPut::getId).collect(Collectors.toList());
        
        Map<Long, List<TakeTicketEntity>> longListMap = ticketService.infoByOrderIds(orderIds);
        
        outPuts.forEach(
            o -> o.setTickets(
                longListMap.getOrDefault(o.getId(), new ArrayList<>()).stream().map(TakeTicketOutPut::toOutput).collect(Collectors.toList())
            )
        );
        
        OrderDataModel<TakeTicketOrderOutPut> orderDataModel = new OrderDataModel<>();
        orderDataModel.setTotal(page.getTotal());
        orderDataModel.setList(outPuts);
        
        TakeTicketOrderEntity order = service.count(input);
        if (Objects.nonNull(order)){
            orderDataModel.setCount(order.getTotalOrders() != null ? order.getTotalOrders() : 0);
            orderDataModel.setTicketCount(order.getTotalTickets() != null ? order.getTotalTickets() : 0);
        }
        
        return orderDataModel;
    }
    
    @Override
    public PageModel<RefundApplyRecordListOutput> refundRecord(RefundRecordInput input) {
        List<Long> inputUserIds = userService.getUserIdByCellphone(input.getCellphone());
        if (StrUtil.isNotEmpty(input.getCellphone()) && inputUserIds.isEmpty()){
            return new PageModel<>();
        }
        input.setUserIds(inputUserIds);
      
        IPage<LaterPayRefundRecordEntity> page = refundApplyRecordsService.iPage(input);
        List<RefundApplyRecordListOutput> outputs = modelUtil.listToList(
            page.getRecords(),
            new TypeToken<List<RefundApplyRecordListOutput>>() { }.getType()
        );
        
        List<Long> userIds = outputs.stream().map(RefundApplyRecordListOutput::getUserId).collect(Collectors.toList());
        List<Long> orderIds = outputs.stream().map(RefundApplyRecordListOutput::getOrderId).collect(Collectors.toList());
        
        Map<Long, String> userIdsWithCellphones = userService.getUserIdsWithCellphones(userIds);
        Map<Long, Short> orderChannelsByIds = orderService.getOrderChannelsByIds(orderIds);
        Map<Long, FilmScheduleEntity> scheduleEntitiesByOrderIds = getScheduleEntitiesByOrderIds(orderIds);
        
        outputs.forEach(output -> {
            output.setCellphone(userIdsWithCellphones.get(output.getUserId()));
            output.setChannel(orderChannelsByIds.get(output.getOrderId()));
            output.setSchedule(new RefundApplyRecordListOutput.Schedule(scheduleEntitiesByOrderIds.get(output.getOrderId())));
        });
        
        return new PageModel<>(
            page.getTotal(),
            outputs
        );
    }
    
    @Override
    public void updateStatus(LaterPayRefundStatusInput input) {
        // 获取当前退款申请记录
        LaterPayRefundRecordEntity refundRecord = refundApplyRecordsService.getById(input.getId());
        if (refundRecord == null) {
            throw new BadRequestException(
                ErrorCode.BAD_REQUEST,
                EscapeUtil.errorMessage("id", "记录不存在")
            );
        }
        
        // 只允许修改状态为“待审核”的记录
        if (refundRecord.getStatus().getValue() != 1) {
            throw new BadRequestException(
                ErrorCode.BUSINESS_ERROR,
                EscapeUtil.errorMessage("status", "仅状态为“待审核”的记录可以修改")
            );
        }
        
        // 更新状态
        refundApplyRecordsService.update(
            new UpdateWrapper<LaterPayRefundRecordEntity>()
                .set("status", input.getStatus())
                .set("message", input.getMessage())
                .eq("id", input.getId())
        );
        
        // 如果状态是通过 (假设通过状态为2)
        if (input.getStatus() == 2) {
            OrderEntity order = orderService.getById(refundRecord.getOrderId());
            
            // 查询会员卡
            MemberCardEntity memberCard = memberCardService.getOneByUserId(order.getUserId());
            
            // 金额
            BigDecimal payPrice = order.getPayPrice();
            
            // 把金额退回会员卡
            memberCardService.refundToCard(memberCard, payPrice);
            
            // 生成“冻结金额退回”的交易记录
            MemberCardOrderRecordEntity transactionRecord = new MemberCardOrderRecordEntity();
            transactionRecord.setSerialNumber(generateSerialNumber.orderNo(""));
            transactionRecord.setFlowType(MemberCardOrderRecordFlowType.INCOME);
            transactionRecord.setType(MemberCardOrderRecordType.FROZEN_AMOUNT_REFUND);
            transactionRecord.setDesc("冻结金额退回");
            transactionRecord.setAmount(payPrice);
            transactionRecord.setBalance(memberCard.getBalance());
            transactionRecord.setCreatedAt(LocalDateTime.now());
            transactionRecord.setUserId(order.getUserId());
            transactionRecord.setFromOrderId(refundRecord.getOrderId());
            transactionRecord.setCardId(memberCard.getId());
            memberCardOrderRecordService.save(transactionRecord);
            
            // 修改先看后付
            OrderTicketLaterPayEntity orderTicketLaterPay = orderTicketLaterPayService.getOneByOrderId(refundRecord.getOrderId());
            orderTicketLaterPay.setStatus(OrderTicketLaterPayStatus.REFUND);
            orderTicketLaterPayService.updateById(orderTicketLaterPay);
        }
    }

    
    
    public Map<Long, FilmScheduleEntity> getScheduleEntitiesByOrderIds(List<Long> orderIds) {
        if (orderIds.size() == 0){
            return new HashMap<>();
        }
       
        // Step 1: 获取 order_tickets 表中对应的 film_schedule_id
        List<OrderTicketEntity> orderTickets = orderTicketService.list(new QueryWrapper<OrderTicketEntity>().in("order_id", orderIds));
        
        // Step 2: 获取 film_schedule_id 列表
        List<Long> filmScheduleIds = orderTickets.stream()
            .map(OrderTicketEntity::getFilmScheduleId)
            .collect(Collectors.toList());
        
        // Step 3: 根据 film_schedule_id 查询 film_schedules 表
        List<FilmScheduleEntity> filmSchedules = filmScheduleService.listByIds(filmScheduleIds);
        
        // Step 4: 创建一个 Map，将 film_schedules 映射为一个 Map，键为 order_id，值为对应的 FilmSchedules 实体
        Map<Long, FilmScheduleEntity> result = new HashMap<>();
        Map<Long, FilmScheduleEntity> filmSchedulesMap = filmSchedules.stream()
            .collect(Collectors.toMap(FilmScheduleEntity::getId, Function.identity()));
        
        for (OrderTicketEntity orderTicket : orderTickets) {
            FilmScheduleEntity filmSchedule = filmSchedulesMap.get(orderTicket.getFilmScheduleId());
            result.put(orderTicket.getOrderId(), filmSchedule);
        }
        
        return result;
    }
}